package top.bigdata.service.impl;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.bigdata.constants.ZoneConstant;
import top.bigdata.mapper.VideoMapper;
import top.bigdata.model.dto.DateWeeklyData;
import top.bigdata.model.dto.MonthlyData;
import top.bigdata.model.dto.video.AvgData;
import top.bigdata.model.dto.video.DurationData;
import top.bigdata.model.entity.Video;
import top.bigdata.service.api.ResultService;
import top.bigdata.service.api.VideoService;

import java.util.*;

@Service
@RequiredArgsConstructor
public class VideoServiceImpl implements VideoService {
    private final VideoMapper videoMapper;
    private final ResultService resultService;

    /**
     * 获取最热视频
     */
    @Override
    public List<Video> getHotVideo(int tid) {
        var tids = ZoneConstant.tidToTids(tid);
        return resultService.cachedQueryList("hot_video_" + tid, () ->
                videoMapper.getHotVideos(tids), Video.class);
    }

    /**
     * 获取分区视频平均播放量
     */
    @Override
    public List<AvgData> getAvgView() {
        List<AvgData> originalData = resultService.cachedQueryList("video_avg_view", videoMapper::getAvgView, AvgData.class);
        return getAvgData(originalData);
    }

    /**
     * 获取分区视频平均点赞数
     */
    @Override
    public List<AvgData> getLike() {
        List<AvgData> originalData = resultService.cachedQueryList("video_avg_like", videoMapper::getLike, AvgData.class);
        return getAvgData(originalData);
    }

    /**
     * 获取分区视频平均硬币数
     */
    @Override
    public List<AvgData> getCoin() {
        List<AvgData> originalData = resultService.cachedQueryList("video_avg_coin", videoMapper::getCoin, AvgData.class);
        return getAvgData(originalData);
    }

    /**
     * 获取分区视频平均收藏数
     */
    @Override
    public List<AvgData> getFavorite() {
        List<AvgData> originalData = resultService.cachedQueryList("video_avg_favorite", videoMapper::getFavorite, AvgData.class);
        return getAvgData(originalData);
    }

    /**
     * 获取分区视频平均分享数
     */
    @Override
    public List<AvgData> getShare() {
        List<AvgData> originalData = resultService.cachedQueryList("video_avg_share", videoMapper::getShare, AvgData.class);
        return getAvgData(originalData);
    }

    /**
     * 获取分区视频平均弹幕数
     */
    @Override
    public List<AvgData> getDanmuku() {
        List<AvgData> originalData = resultService.cachedQueryList("video_avg_danmuku", videoMapper::getDanmuku, AvgData.class);
        return getAvgData(originalData);
    }

    /**
     * 获取分区视频平均评论数
     */
    @Override
    public List<AvgData> getReply() {
        List<AvgData> originalData = resultService.cachedQueryList("video_avg_reply", videoMapper::getReply, AvgData.class);
        return getAvgData(originalData);
    }

    /**
     * 获取分区视频月度数据
     */
    @Override
    public List<MonthlyData> getDataMonthly(int tid) {
        var tids = ZoneConstant.tidToTids(tid);
        var result = resultService.cachedQueryList("video_avg_monthly_" + tid, () ->
                videoMapper.getDataMonthly(tids), MonthlyData.class);
        // 排序
        result.sort(Comparator.comparing(MonthlyData::getMonth));
        return result;
    }

    /**
     * 获取分区视频周度数据
     */
    @Override
    public List<DateWeeklyData> getDataWeekly(int tid) {
        var tids = ZoneConstant.tidToTids(tid);
        var result = resultService.cachedQueryList("video_avg_dateWeekly_" + tid, () ->
                videoMapper.getDataWeekly(tids), DateWeeklyData.class);
        // 排序
        result.sort(Comparator.comparing(DateWeeklyData::getWeek));

        // 将星期转换为中文
        List<String> weekDays = Arrays.asList("1", "星期日", "星期一", "星期二",
                "星期三", "星期四", "星期五", "星期六");
        result.forEach(d -> d.setWeek(weekDays.get(Integer.parseInt(d.getWeek()))));
        return result;
    }

    /**
     * 获取不同时长的视频数据
     */
    @Override
    public List<DurationData> getDurationData(int tid) {
        var tids = ZoneConstant.tidToTids(tid);
        var result = resultService.cachedQueryList("video_duration_" + tid, () ->
                videoMapper.getDurationData(tids), DurationData.class);

        // 计算比重
        int sumCount = 0;
        for (var data : result) {
            sumCount += data.getCount();
        }
        for (var data : result) {
            data.setProportion(data.getCount() / (double) sumCount);
        }

        // 排序
        result.sort(Comparator.comparing(DurationData::getDuration));
        // 将时长转换为中文
        String[] durations = {"0-5分钟", "5-10分钟", "10-20分钟", "20-30分钟", "30-60分钟", "60分钟以上" };
        result.forEach(d -> d.setDuration(durations[Integer.parseInt(d.getDuration())]));
        return result;
    }

    /**
     * 获取视频平均数据
     */
    private List<AvgData> getAvgData(List<AvgData> originalData) {
        List<AvgData> result = new ArrayList<>();

        // 建立主分区数据
        var mainZoneDataMap = new HashMap<Integer, AvgData>();
        for (var mainZone : ZoneConstant.MAIN_ZONES) {
            mainZoneDataMap.put(mainZone.getTid(), new AvgData(mainZone.getTid(), mainZone.getName(), 0, 0));
        }

        // 添加子分区数据
        for (var data : originalData) {
            data.setName(ZoneConstant.getZoneName(data.getTid()));
            var mainZoneData = mainZoneDataMap.get(ZoneConstant.getMainZoneId(data.getTid()));
            if (mainZoneData != null) {
                mainZoneData.getSubZones().add(data);
            }
        }
        // 根据子分区数据统计主分区数据
        for (var mainZoneData : mainZoneDataMap.values()) {
            long sum = 0;
            int count = 0;
            for (var subZoneData : mainZoneData.getSubZones()) {
                sum += subZoneData.getAvg() * subZoneData.getCount();
                count += subZoneData.getCount();
            }
            if (count != 0)
                mainZoneData.setAvg(sum / count);
            mainZoneData.setCount(count);
            result.add(mainZoneData);
        }

        return result;
    }
}
